<div id="vue-good-sku" style="width: 100%"></div>
<script>
    Dcat.ready(function () {
        window.appInit('#vue-good-sku',{
            template: `
<div>
    <n-table class="table" >
        <n-thead>
            <n-tr>
                <n-th style="width: 100px">设置规格名称</n-th>
                <n-th >
                    <n-space>
                    <template v-for="(item,index) in rules">
                        <n-input v-if="item.show" v-model:value="item.label" placeholder="请输入规格名称" @blur="item.show = false"></n-input>
                        <n-tag v-else closable @close="handleClose(index)" @click='item.show = true'>
                            <span>@{{item.label}}</span>
                        </n-tag>
                    </template>
                        <n-input v-if="showRule" placeholder="请输入规格名称"  v-model:value="ruleName" @blur="onCreate"></n-input>
                        <n-button
                            v-else
                            size="small"
                            type="primary"
                            dashed
                            @click="showRule = true"
                        >
                            <template #icon>
                                <n-icon>
                                    <svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M256 112V400M400 256H112" stroke="currentColor" stroke-width="32" stroke-linecap="round" stroke-linejoin="round"></path></svg>
                                </n-icon>
                            </template>
                            添加
                        </n-button>
                    </n-space>
                </n-th>
            </n-tr>
        </n-thead>
        <n-tbody>
            <template v-for="(item,index) in rules">
                <n-tr>
                    <n-td style="width: 100px">@{{item.label}}</n-td>
                    <n-td >
                    <n-space>
                    <n-p>规格值:</n-p>
                        <template v-for="(child,key) in item.children">
                            <n-input v-if="child.show" v-model:value="child.label" placeholder="请输入规格名称" @blur="child.show = false"></n-input>
                            <n-tag v-else closable @close="handleItemClose(index,key)" @click='child.show = true'>
                                <span>@{{child.label}}</span>
                            </n-tag>
                        </template>
                        <n-input v-if="item.showCreate" v-model:value="item.itemName" placeholder="请输入值"  @blur="e=>onItemCreate(index,e)"></n-input>
                        <n-button
                            v-else
                            size="small"
                            type="primary"
                            dashed
                            @click="item.showCreate = true"
                        >
                            <template #icon>
                                <n-icon>
                                    <svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M256 112V400M400 256H112" stroke="currentColor" stroke-width="32" stroke-linecap="round" stroke-linejoin="round"></path></svg>
                                </n-icon>
                            </template>
                            添加
                        </n-button>
                    </n-space>
                    </n-td>
                </n-tr>
            </template>
        </n-tbody>
    </n-table>
    <n-button v-if="skuList.length" type="default" size="small" @click="showDialog = true"> 批量设置 </n-button>
    <n-modal v-model:show="showDialog" preset="dialog" title="Dialog" @close="showDialog=false">
        <template #header>
            <div>标题</div>
        </template>
        <div>
            <n-form-item label="批量设置库存" label-align="left" path="stock">
                <n-input-number
                    v-model:value="form.stock"
                    placeholder="输入库存"
                    :step="1"
                ></n-input-number>
            </n-form-item>
            <n-form-item label="批量设置售价" label-align="left"  path="price">
                <n-input-number
                    v-model:value="form.price"
                    placeholder="输入售价"
                    :step="1"
                    :precision="2"
                >
                    <template #prefix>
                        <i class="fa fa-rmb"></i>
                    </template>
                </n-input-number>
            </n-form-item>
        </div>
        <template #action>
            <n-button  type="primary" size="small" @click="onMultUpdate"> 确认 </n-button>
        </template>
    </n-modal>
    <n-table class="table" >
        <n-thead>
            <n-tr>
                <n-th>规格属性</n-th><n-th>图片</n-th><n-th>库存</n-th><n-th>价格</n-th>
            </n-tr>
        </n-thead>
        <n-tbody>
            <template v-for="(sku,index) in skuList">
                <n-tr>
                    <n-th>@{{getSkuAttrs(sku)}}</n-th>
                    <n-td>
        <n-upload
            action="{{$uploadUrl}}"
            accept="image/*"
            :default-file-list="sku.fileList"
            list-type="image-card"
            :max="1"
            @before-upload="beforeUpload"
            @finish="(e)=>handleFinish(e,index)"
            @remove="(e)=>handleRemove(e,index)"
        >
            点击上传
        </n-upload>
</n-td>
                    <n-td><n-input-number
                        v-model:value="sku.stock"
                        placeholder="库存"
                        :step="1"
                        style="width: 180px"
                    ></n-input-number></n-td>
                    <n-td><n-input-number
                            v-model:value="sku.price"
                            placeholder="输入售价"
                            :step="1"
                            :precision="2"
                            style="width: 180px"
                        >
                            <template #prefix>
                                <i class="fa fa-rmb"></i>
                            </template>
                        </n-input-number>
                    </n-td>
                </n-tr>
            </template>
        </n-tbody>
    </n-table>
    <input type="hidden" name="sku" :value="skuListJson">
</div>
            `,
            data(){
                return {
                    sku: JSON.parse(@json($sku)),
                    rules: [],
                    labels: [],
                    skuList: [],
                    showDialog: false,
                    showRule: false,
                    showRules:[],
                    ruleName:"",
                    form: {
                        stock: null,
                        price: null,
                        start_price: null,
                        end_price: null,
                    }
                }
            },
            computed:{
                skuListJson(){
                    return JSON.stringify({
                        attrs:this.sku.attrs,
                        sku:this.skuList
                    })
                },
                skus(){
                    this.labels = [];
                    let list = [];
                    if(!this.sku.attrs){
                        this.sku.attrs = {};
                    }
                    let attrs = {}
                    this.rules.forEach(item=>{
                        if(item){
                            this.labels.push(item.label)
                            if(item.children&&item.children.length){
                                list.push(item.children.map(x=>x.label))
                            }
                            attrs[item.label] = item.children
                        }
                    })
                    this.sku.attrs = attrs;
                    return this.calcDescartes(list)
                }
            },
            created() {
                this.setRules();
            },
            watch:{
                rules: {
                    deep: true,
                    handler(){
                        this.setSkus();
                    }
                }
            },
            methods:{
                setSkus(){
                    this.skuList = [];
                    if(!this.sku){
                        this.sku.sku = [];
                    }
                    const sku = this.sku.sku?this.sku.sku:[];
                    this.skus?.forEach((item,index)=>{
                        let newSku = {price: null, stock: 0, start_price:null, end_price: null, pic:null};
                        if(sku[index]!==undefined){
                            const oldSku = sku[index];
                            newSku.price = oldSku.price;
                            newSku.stock = oldSku.stock
                            newSku.start_price = oldSku.start_price;
                            newSku.end_price = oldSku.end_price;
                            newSku.pic = oldSku.pic;
                        }
                        newSku.price = Number(newSku.price)
                        newSku.stock = Number(newSku.stock)
                        newSku.start_price = Number(newSku.start_price)
                        newSku.end_price = Number(newSku.end_price)
                        if(newSku.pic){
                            newSku.fileList = [{url:newSku.pic,id:-1, status: 'finished'}]
                        }
                        if(item&&item.length>0){
                            item.forEach((m,i)=>{
                                newSku[this.labels[i]] = m;
                            })
                        }
                        this.skuList.push(newSku)
                    })
                },
                calcDescartes(array){
                    if (array.length === 0 ) return [];
                    if (array.length === 1) return array[0].map(x=>[x]);
                    return array.reduce((total, currentValue) => {
                        let res = [];
                        total.forEach((t) => {
                            currentValue.forEach(cv => {
                                if (t instanceof Array){
                                    res.push([...t, cv]);
                                }else{
                                    res.push([t, cv]);
                                }
                            })
                        })
                        return res;
                    })
                },
                setRules(){
                    const sku = this.sku;
                    if(sku){
                        for (let index in sku.attrs) {
                            this.rules.push({
                                label: index,
                                show: false,
                                showCreate: false,
                                children: sku.attrs[index].map(item=>{
                                    item.show = false;
                                    return item;
                                })
                            })
                        }
                    }
                },
                getSkuAttrs(sku){
                    let attrs = [];
                    Object.keys(sku).forEach((key)=>{
                        if(key!=='price'&&key!=='start_price'&&key!=='end_price'&&key!=='price'&&key!=='stock'&&key!=='pic'&&key!=='fileList'){
                            attrs.push(sku[key])
                        }
                    })
                    return attrs.join(" - ");
                },
                onCreate(){
                    if(this.ruleName){
                        this.rules.push({
                            label: this.ruleName,
                            show: false,
                            showCreate: false,
                            itemName: "",
                            children: []
                        })
                    }
                    this.ruleName = "";
                    this.showRule = false;
                },
                handleClose(index){
                    this.rules.splice(index,1)
                },
                handleItemClose(index,key){
                    this.rules[index].children.splice(key,1)
                },
                onItemCreate(index, label){
                    const itemName = this.rules[index].itemName
                    if(itemName){
                        this.rules[index].children.push({
                            label: itemName,
                            show: false
                        })
                    }
                    this.rules[index].itemName = "";
                    this.showCreate = false;
                },
                onMultUpdate(){
                    let t = 0;
                    for (let i in this.form) {
                        t += this.form[i]?1:0;
                    }
                    if(!t){
                        window.$message.error("请输入至少一个设置批量值!")
                        return false;
                    }
                    for (let i in this.form) {
                        if(this.form[i]){
                            this.skuList = this.skuList.map(item=>{
                                item[i] = this.form[i];
                                return item;
                            })
                            this.form[i] = null;
                        }
                    }
                    this.showDialog = false;
                },
                beforeUpload(data){
                    if(data.file.file?.type !== 'image/png'&&
                        data.file.file?.type !== 'image/jpg'&&
                        data.file.file?.type !== 'image/jpeg'&&
                        data.file.file?.type !== 'image/bmp'
                    ) {
                        window.$message.error('只能上传png,jpg,jpeg,bmp图片文件，请重新上传')
                        return false
                    }
                    return true
                },
                handleFinish(e,index){
                    let file = e.file;
                    const XMLHttpRequest = e.event?.target;
                    if(XMLHttpRequest.status===200){
                       const result = JSON.parse(XMLHttpRequest.responseText)
                        if(result.status){
                            window.$message.success(result.data.message)
                            file.url = result.data.url
                            this.skuList[index].pic = file.url
                        }else{
                            window.$message.error(result.data.message);
                            file.status = "error";
                        }
                    }else{
                        file.status = "error";
                    }
                    return file
                },
                handleRemove(e,index){
                    return new Promise(resolve => {
                        window.$dialog.error({
                            title: '删除SKU图片',
                            content: '是否确认删除SKU图片',
                            positiveText: '确认',
                            negativeText: '关闭',
                            onPositiveClick: () => {
                                this.skuList[index].pic = "";
                                this.skuList[index].fileList = [];
                                resolve(true);
                            },
                            onClose:()=>{
                                resolve(false);
                            }
                        })
                    })
                }
            }
        })
    })
</script>
